package com.zsk.shop.config.pay;

import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import com.zsk.shop.api.pay.common.api.PayService;
import com.zsk.shop.api.pay.common.http.HttpConfigStorage;
import com.zsk.shop.api.pay.wx.api.WxPayConfigStorage;
import com.zsk.shop.api.pay.wx.api.WxPayService;
import com.zsk.shop.common.utils.HttpUtil;
import com.zsk.shop.service.ShopOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付参数配置
 *
 * @author Administrator
 */
@Slf4j
@Configuration
public class WeixinPayConfig {

    @Autowired
    private Environment environment;

    private static final Logger logger = LoggerFactory.getLogger(ShopOrderService.class);

    /**
     * APP支付
     *
     * @return
     */
    @Bean
    public PayService getPayServiceAPP() {
        WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
        wxPayConfigStorage.setMchId(environment.getProperty("pay.weixin.mini.mchID"));
        wxPayConfigStorage.setAppid(environment.getProperty("pay.weixin.mini.appId"));
        wxPayConfigStorage.setSecretKey(environment.getProperty("pay.weixin.mini.key"));
        wxPayConfigStorage.setNotifyUrl(environment.getProperty("pay.weixin.mini.notifyUrl"));
        wxPayConfigStorage.setSignType("MD5");
        wxPayConfigStorage.setInputCharset("utf-8");
        PayService service = new WxPayService(wxPayConfigStorage);
        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
        //ssl 退款证书相关 不使用可注释
        httpConfigStorage.setKeystore(environment.getProperty("pay.weixin.mini.certPath"));
        httpConfigStorage.setStorePassword(environment.getProperty("pay.weixin.mini.mchID"));
        httpConfigStorage.setPath(true);
        //请求连接池配置
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
        return service;
    }

    /**
     * wxAPP支付
     *
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author Ys
     * @date 2021/3/31 9:42
     */
    public Map<String, String> wxPay(String tradeNo, BigDecimal price, String body) throws Exception {
        Map<String, String> parameters = buildWeChatPayOrderMap(tradeNo, price, body);
        //设置签名--微信SKD提供了获取签名的方法
        String sign = WXPayUtil.generateSignature(parameters, environment.getProperty("pay.weixin.app.key"));
        parameters.put("sign", sign);
        //封装请求参数结束 将map转xml
        String requestXML = WXPayUtil.mapToXml(parameters);
        /**统一下单接口返回正常的prepay_id，再按签名规范重新生成签名后，将数据传输给APP。参与签名的字段名为appId，partnerId，prepayId，nonceStr，timeStamp，package。注意：package的值格式为Sign=WXPay**/
        String result = httpPostXML(environment.getProperty("pay.weixin.app.payUrl"), requestXML);
        log.info("\n 微信验证签名后返回" + result);
        // 预支付id
        String prepay_id = "";
        //判断统一下单是否成功
        if (result.indexOf("SUCCESS") != -1) {
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            prepay_id = map.get("prepay_id");
        }
        Map<String, String> payMap = new HashMap<>();
        payMap.put("appid", environment.getProperty("pay.weixin.app.appId"));
        payMap.put("partnerid", environment.getProperty("pay.weixin.app.mchID"));
        //预支付id
        payMap.put("prepayid", prepay_id);
        payMap.put("noncestr", WXPayUtil.generateNonceStr());
        payMap.put("package", "Sign=WXPay");
        payMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000).substring(0, 10));
        String paySign = WXPayUtil.generateSignature(payMap, environment.getProperty("pay.weixin.app.key"));
        payMap.put("sign", paySign);
        return payMap;
    }

    /**
     * wxH5支付
     *
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author Ys
     * @date 2021/3/31 9:42
     */
    public Map<String, String> wxH5Pay(String tradeNo, BigDecimal price, String body) throws Exception {
        Map<String, String> parameters = getPayServiceH5(tradeNo, price, body);
        //设置签名--微信SKD提供了获取签名的方法
        String sign = WXPayUtil.generateSignature(parameters, environment.getProperty("pay.weixin.js.key"));
        parameters.put("sign", sign);
        //封装请求参数结束 将map转xml
        String requestXML = WXPayUtil.mapToXml(parameters);
        /**统一下单接口返回正常的prepay_id，再按签名规范重新生成签名后，将数据传输给APP。参与签名的字段名为appId，partnerId，prepayId，nonceStr，timeStamp，package。注意：package的值格式为Sign=WXPay**/
        String result = httpPostXML(environment.getProperty("pay.weixin.js.payUrl"), requestXML);
        log.info("\n 微信验证签名后返回" + result);
        // 预支付id
        String prepay_id = "";
        //判断统一下单是否成功
        if (result.indexOf("SUCCESS") != -1) {
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            prepay_id = map.get("prepay_id");
        }
        Map<String, String> payMap = new HashMap<>();
        payMap.put("appid", environment.getProperty("pay.weixin.js.appId"));
        payMap.put("partnerid", environment.getProperty("pay.weixin.js.mchID"));
        //预支付id
        payMap.put("prepayid", prepay_id);
        payMap.put("noncestr", WXPayUtil.generateNonceStr());
        payMap.put("package", "Sign=WXPay");
        payMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000).substring(0, 10));
        String paySign = WXPayUtil.generateSignature(payMap, environment.getProperty("pay.weixin.js.key"));
        payMap.put("sign", paySign);
        return payMap;
    }

    /**
     * post请求并得到返回结果
     *
     * @param requestUrl
     * @param xml
     * @return
     */
    public static String httpPostXML(String requestUrl, String xml) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(requestUrl);
        StringEntity postEntity = new StringEntity(xml, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml;charset=UTF-8");
        httpPost.setEntity(postEntity);
        try {
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity, "UTF-8");
        } catch (Exception var7) {
        }
        return "";
    }

    /**
     * 构造微信支付订单参数列表
     */
    private Map<String, String> buildWeChatPayOrderMap(String tradeNo, BigDecimal price, String body) {
        Map<String, String> parameters = new HashMap<>();
        parameters.put("appid", environment.getProperty("pay.weixin.app.appId"));
        parameters.put("mch_id", environment.getProperty("pay.weixin.app.mchID"));
        //32位以内的随机数
        parameters.put("nonce_str", WXPayUtil.generateNonceStr());
        //购买内容
        parameters.put("body", body);
        //订单id
        parameters.put("out_trade_no", tradeNo);
        parameters.put("fee_type", "CNY");
        //	微信中金额 1=0.01元。所以计算金额记得换算  X*100 支付金额单位为【分】*100
        int money = price.multiply(new BigDecimal(100)).intValue();
        parameters.put("total_fee", String.valueOf(money));
        parameters.put("spbill_create_ip", HttpUtil.getIp());
        //回调接口地址
        parameters.put("notify_url", environment.getProperty("pay.weixin.app.notifyUrl"));
        parameters.put("trade_type", "APP");
        return parameters;
    }

    /**
     * 小程序支付
     *
     * @return
     */
    @Bean
    public PayService getPayServiceMINI() {
        WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
        wxPayConfigStorage.setMchId(environment.getProperty("pay.weixin.mini.mchID"));
        wxPayConfigStorage.setAppid(environment.getProperty("pay.weixin.mini.appId"));
        wxPayConfigStorage.setSecretKey(environment.getProperty("pay.weixin.mini.key"));
        wxPayConfigStorage.setNotifyUrl(environment.getProperty("pay.weixin.mini.notifyUrl"));
        wxPayConfigStorage.setSignType("MD5");
        wxPayConfigStorage.setInputCharset("utf-8");
        PayService service = new WxPayService(wxPayConfigStorage);
        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
        //ssl 退款证书相关 不使用可注释
        httpConfigStorage.setKeystore(environment.getProperty("pay.weixin.mini.certPath"));
        httpConfigStorage.setStorePassword(environment.getProperty("pay.weixin.mini.mchID"));
        httpConfigStorage.setPath(true);
        //请求连接池配置
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
        return service;
    }

    /**
     * 公众号支付
     *
     * @return
     */
    @Bean
    public PayService getPayServiceJSAPI() {
        WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
        wxPayConfigStorage.setMchId(environment.getProperty("pay.weixin.js.mchID"));
        wxPayConfigStorage.setAppid(environment.getProperty("pay.weixin.js.appId"));
        wxPayConfigStorage.setSecretKey(environment.getProperty("pay.weixin.js.key"));
        wxPayConfigStorage.setNotifyUrl(environment.getProperty("pay.weixin.js.notifyUrl"));
        wxPayConfigStorage.setSignType("MD5");
        wxPayConfigStorage.setInputCharset("utf-8");
        PayService service = new WxPayService(wxPayConfigStorage);
        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
        //ssl 退款证书相关 不使用可注释
//        httpConfigStorage.setKeystore(environment.getProperty("pay.weixin.js.certPath"));
        httpConfigStorage.setStorePassword(environment.getProperty("pay.weixin.js.mchID"));
        httpConfigStorage.setPath(true);
        //请求连接池配置
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
        return service;
    }

    /**
     * H5支付
     *
     * @return
     */
    @Bean
    public PayService getPayServiceH5() {
        WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
        wxPayConfigStorage.setMchId(environment.getProperty("pay.weixin.js.mchID"));
        wxPayConfigStorage.setAppid(environment.getProperty("pay.weixin.js.appId"));
        wxPayConfigStorage.setSecretKey(environment.getProperty("pay.weixin.js.key"));
        wxPayConfigStorage.setNotifyUrl(environment.getProperty("pay.weixin.js.notifyUrl"));
        wxPayConfigStorage.setSignType("MD5");
        wxPayConfigStorage.setInputCharset("utf-8");
        PayService service = new WxPayService(wxPayConfigStorage);
        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
        //ssl 退款证书相关 不使用可注释
        httpConfigStorage.setKeystore(environment.getProperty("pay.weixin.js.certPath"));
        httpConfigStorage.setStorePassword(environment.getProperty("pay.weixin.js.mchID"));
        httpConfigStorage.setPath(true);
        //请求连接池配置
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
        return service;
    }

    /**
     *  H5支付
     * @param tradeNo
     * @param price
     * @param body
     * @throws IOException
     */
    private  Map<String, String> getPayServiceH5(String tradeNo, BigDecimal price, String body) throws IOException {
        Map<String, String> parameters = new HashMap<>();
        parameters.put("appid", environment.getProperty("pay.weixin.app.appId"));
        parameters.put("mch_id", environment.getProperty("pay.weixin.app.mchID"));
        //32位以内的随机数
        parameters.put("nonce_str", WXPayUtil.generateNonceStr());
        //购买内容
        parameters.put("description", body);
        //订单id
        parameters.put("out_trade_no", tradeNo);
        parameters.put("fee_type", "CNY");
        //	微信中金额 1=0.01元。所以计算金额记得换算  X*100 支付金额单位为【分】*100
        int money = price.multiply(new BigDecimal(100)).intValue();
        parameters.put("total_fee", String.valueOf(money));
        parameters.put("spbill_create_ip", HttpUtil.getIp());
        //回调接口地址
        parameters.put("notify_url", environment.getProperty("pay.weixin.app.notifyUrl"));
        parameters.put("trade_type", "MWEB");
        Map<String, String> map = new HashMap<>();
        map.put("type", "Wap");
        map.put("wap_url", "");
        map.put("wap_name", "商品购买");
        parameters.put("h5_info", new Gson().toJson(map));
        return parameters;
    }

}
